package cn.hg.solon.youcan.job.kit;

import java.util.Date;

import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.exception.ExceptionUtil;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.cron.task.Task;
import org.noear.solon.Solon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hg.solon.youcan.job.constant.JobExecuteStatus;
import cn.hg.solon.youcan.job.entity.SysJob;
import cn.hg.solon.youcan.job.entity.SysJobLog;
import cn.hg.solon.youcan.job.service.SysJobLogService;

/**
 * 抽象quartz调用
 *
 * @author ruoyi
 */
public abstract class AbstractCronJob implements Task {
	protected Date startTime;
	protected Date createTime;

	protected Logger log = LoggerFactory.getLogger(this.getClass());

	private SysJob job;

	public AbstractCronJob(SysJob job) {
		this.job = job;
		this.createTime = DateUtil.now();
	}

	/**
	 * 执行后
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 */
	protected void after(Object result, Throwable e) {
		final SysJobLog sysJobLog = new SysJobLog();
		sysJobLog.setName(this.job.getName());
		sysJobLog.setGroup(this.job.getGroup());
		sysJobLog.setTarget(this.job.getTarget());
		sysJobLog.setCreatedDatetime(this.createTime);
		sysJobLog.setStartedDatetime(this.startTime);
		sysJobLog.setEndedDatetime(DateUtil.now());
		sysJobLog.setCost(sysJobLog.getEndedDatetime().getTime() - sysJobLog.getStartedDatetime().getTime());
        sysJobLog.setMessage(sysJobLog.getName() + "，耗时：" + sysJobLog.getCost() + "毫秒");
		if (e != null) {
			sysJobLog.setStatus(JobExecuteStatus.FAILED);
			String errorMsg = CharSequenceUtil.sub(ExceptionUtil.stacktraceToString(e) , 0, 2000);
			sysJobLog.setException(errorMsg);
            sysJobLog.setMessage(sysJobLog.getMessage() + "，异常：" + e.getMessage());
		} else {
			sysJobLog.setStatus(JobExecuteStatus.SUCCESSED);
		}

		this.startTime = null;

		// 写入数据库当中
        Solon.context().getBean(SysJobLogService.class).save(sysJobLog);
	}

	/**
	 * 执行前
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 */
	protected void before() {
		this.startTime = DateUtil.now();
	}

	/**
	 * 执行方法，由子类重载
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 * @return 返回对象
	 * @throws Exception 执行过程中的异常
	 */
	protected abstract Object doExecute() throws Throwable;

	@Override
    public void execute() {
		Object result = null;
		try {
			this.before();
			result = this.doExecute();
			this.after(result, null);
		} catch (Throwable e) {
			this.log.error("任务执行异常  - ：", e);
			this.after(result, e);
		}
	}

	public SysJob getJob() {
		return this.job;
	}
}
